package org.dromara.basic.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dromara.basic.domain.Member;
import org.dromara.basic.domain.bo.MemberBo;
import org.dromara.basic.domain.vo.DeviceVo;
import org.dromara.basic.domain.vo.MemberVo;
import org.dromara.basic.mapper.MemberMapper;
import org.dromara.basic.service.IDictService;
import org.dromara.basic.service.IMemberService;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.utils.FileUploadUtils;
import org.dromara.utils.Utils;
import org.dromara.utils.domain.JsonResponse;
import org.dromara.utils.service.SynchronizeImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.annotation.AccessType;
import org.springframework.stereotype.Service;
import org.dromara.basic.domain.bo.FaceImageBo;
import org.dromara.basic.domain.vo.FaceImageVo;
import org.dromara.basic.domain.FaceImage;
import org.dromara.basic.mapper.FaceImageMapper;
import org.dromara.basic.service.IFaceImageService;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

/**
 * 学生人脸信息Service业务层处理
 *
 * @author chl
 * @date 2024-10-17
 */
@RequiredArgsConstructor
@Service
public class FaceImageServiceImpl implements IFaceImageService {

    // 注入线程池
    @Autowired
    @Qualifier("globalThreadPool")
    private ExecutorService globalThreadPool;

    private final FaceImageMapper baseMapper;
    private final IMemberService memberService;
    private final SynchronizeImageService synchronizeImageService;
    private final IDictService dictTypeService;


    /**
     * 查询学生人脸信息
     */
    @Override
    public FaceImageVo queryById(Long id) {
        FaceImageBo  bo=new FaceImageBo();
        bo.setId(id);
        QueryWrapper<FaceImage> lqw = buildQueryWrapper(bo);
        return baseMapper.selectFaceImageVoOne(lqw);
    }

    /**
     * 查询学生人脸信息列表
     */
    @Override
    public TableDataInfo<FaceImageVo> queryPageList(FaceImageBo bo, PageQuery pageQuery) {
        QueryWrapper<FaceImage> lqw = buildQueryWrapper(bo);
        Page<FaceImageVo> result = baseMapper.selectFaceImageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询学生人脸信息列表
     */
    @Override
    public List<FaceImageVo> queryList(FaceImageBo bo) {
        QueryWrapper<FaceImage> lqw = buildQueryWrapper(bo);
        return baseMapper.selectFaceImageList(lqw);
    }

    private QueryWrapper<FaceImage> buildQueryWrapper(FaceImageBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<FaceImage> lqw = new QueryWrapper<>();
        lqw.eq(StringUtils.isNotBlank(bo.getStuNum()), "pbi.stu_num", bo.getStuNum());
        lqw.in(CollectionUtils.isNotEmpty(bo.getStuNums()), "pbi.stu_num", bo.getStuNums());
        lqw.eq(StringUtils.isNotBlank(bo.getCheckStatus()), "pbi.check_status", bo.getCheckStatus());
        lqw.eq(bo.getClassId() != null, "pmi.class_id", bo.getClassId());
        lqw.eq(bo.getId() != null, "pbi.id", bo.getId());
        lqw.like(StringUtils.isNotBlank(bo.getStudentName()), "pmi.name", bo.getStudentName());
        lqw.orderByAsc("pbi.stu_num");
        return lqw;
    }

    /**
     * 新增学生人脸信息
     */
    @Override
    public Boolean insertByBo(FaceImageBo bo) {
        FaceImage add = MapstructUtils.convert(bo, FaceImage.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改学生人脸信息
     */
    @Override
    public Boolean updateByBo(FaceImageBo bo) {
        FaceImage update = MapstructUtils.convert(bo, FaceImage.class);
//        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(FaceImage entity) {
        List<FaceImageVo> faceImageVo = this.selectVoListByStuNum(entity.getStuNum());
        if (CollectionUtils.isNotEmpty(faceImageVo)) {
            throw new ServiceException("已存在该学生");
        }
    }

    /**
     * 批量删除学生人脸信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    public Boolean synchronizeImage(List<MultipartFile> files) {
        for (MultipartFile file : files) {
            MemberVo memberVo;
            String originalFilename = file.getOriginalFilename();
            String name = FileNameUtil.getPrefix(originalFilename);
            memberVo = memberService.queryByStudentName(name);
            if (ObjectUtils.isEmpty(memberVo)) {
                memberVo = memberService.queryByIdNumber(name);
            }
            this.synchronizeImages(memberVo,file);
        }
        return true;
    }
    public Boolean synchronizeImage(MultipartFile file,FaceImageBo faceImageBo) {
        MemberVo memberVo;
        String originalFilename = file.getOriginalFilename();
        String name = FileNameUtil.getPrefix(originalFilename);
        memberVo = memberService.queryByIdNumber(faceImageBo.getStuNum());
        if (ObjectUtils.isEmpty(memberVo)) {
            memberVo = memberService.queryByStudentName(name);
        }
        if (ObjectUtils.isNotEmpty(memberVo)) {
            FaceImageVo faceImageVo;
            if(faceImageBo.getId()!=null){
                faceImageVo= this.queryById(faceImageBo.getId());
            }else {
                faceImageVo = this.selectVoByStuNum(memberVo.getIdNumber());
            }
            memberVo.setFileType("studentFaceImage");
            String url = FileUploadUtils.uploadFile(file, memberVo);
            if (ObjectUtils.isNotEmpty(faceImageVo)) {
                faceImageBo.setId(faceImageVo.getId());
                if (StringUtils.isNotEmpty(url)) {
                    faceImageBo.setImageUrl(url);
                    Boolean b = this.updateByBo(faceImageBo);
                    if (!b) {
                        FileUploadUtils.delFile(url);
                        throw new ServiceException("更新学生图片失败");
                    }
                }
            }else {
                faceImageBo.setImageUrl(url);
                Boolean b1 = this.insertByBo(faceImageBo);
                if (!b1) {
                    FileUploadUtils.delFile(url);
                    throw new ServiceException("添加学生图片信息成功");
                }
            }
        }
        return true;
    }
    private void synchronizeImages(MemberVo memberVo,MultipartFile file){
        if (ObjectUtils.isNotEmpty(memberVo)) {
            FaceImageVo faceImageVo = this.selectVoByStuNum(memberVo.getIdNumber());
            if (ObjectUtils.isNotEmpty(faceImageVo)) {
                memberVo.setFileType("studentFaceImage");
                String url = FileUploadUtils.uploadFile(file, memberVo);
                FaceImageBo faceImageBo = new FaceImageBo();
                faceImageBo.setId(faceImageVo.getId());
                if (StringUtils.isNotEmpty(url)) {
                    faceImageBo.setImageUrl(url);
                    Boolean b = this.updateByBo(faceImageBo);
                    if (!b) {
                        FileUploadUtils.delFile(url);
                    }
                }
            }
        }
    }

    /**
     * 同步设备
     */
    public Boolean synchronizeDeviceBatch(FaceImageBo faceImageBo) {
        if (ObjectUtils.isNotEmpty(faceImageBo) && CollectionUtils.isEmpty(faceImageBo.getDeviceIps())) {
            throw new ServiceException("请选择要同步的设备");
        }
        if (ObjectUtils.isNotEmpty(faceImageBo) && StringUtils.isEmpty(faceImageBo.getExecutionType())) {
            throw new ServiceException("操作类型不能为空");
        }
        List<FaceImageVo> faceImageVos = this.queryList(faceImageBo);
        if (CollectionUtils.isEmpty(faceImageVos)) {
            throw new ServiceException("暂无学生头像可同步");
        }
        List<Future<?>> futures = new ArrayList<>();

        // 通过全局线程池执行任务
        for (FaceImageVo faceImageVo : faceImageVos) {
            List<DeviceVo> deviceVos = new ArrayList<>();
            if (StringUtils.isNotEmpty(faceImageVo.getDeviceInfo())) {
                String deviceInfo = faceImageVo.getDeviceInfo();
                deviceVos = Utils.parseDeviceVoJson(deviceInfo);
            }
            LoginUser loginUser= LoginHelper.getLoginUser();
            List<DeviceVo> finalDeviceVos = deviceVos;
            for (String ip : faceImageBo.getDeviceIps()) {
                // 创建任务
                Runnable task = () -> {
                    String url = "http://" + ip + "/api/v1/uid/known/" + faceImageBo.getExecutionType();
                    DeviceVo deviceVo = new DeviceVo();
                    if (StringUtils.isNotEmpty(faceImageVo.getImageUrl())) {
                        File file = new File(faceImageVo.getImageUrl());
                        String studentName = faceImageVo.getStudentName();
                        String code="";
                        JsonResponse jsonResponse = synchronizeImageService.sendImageIntoDevice(file, faceImageVo.getStuNum(), url, studentName);
                        if (ObjectUtils.isNotEmpty(jsonResponse)) {
                            String deviceName = dictTypeService.getDictName("device_service_ip", ip,loginUser.getTenantId());
                            deviceVo.setDeviceIp(ip);
                            deviceVo.setDeviceName(deviceName);
                            if(StringUtils.isNotEmpty(jsonResponse.getCode().toString())){
                                if ("add".equals(faceImageBo.getExecutionType())) {
                                    if("0".equals(jsonResponse.getCode().toString())){
                                        code="10";
                                    }else if("501".equals(jsonResponse.getCode().toString())){
                                        code="41";
                                    }else {
                                        code="11";
                                    }
                                }else if("update".equals(faceImageBo.getExecutionType())){
                                    if("0".equals(jsonResponse.getCode().toString())){
                                        code="20";
                                    }else if("501".equals(jsonResponse.getCode().toString())){
                                        code="41";
                                    }else {
                                        code="21";
                                    }
                                }
                            }
                            deviceVo.setSynchronizeStatus(code);
                            deviceVo.setSynchronizeMsg(jsonResponse.getMessage());
                        }
                        synchronized (finalDeviceVos) {
                            finalDeviceVos.removeIf(device -> ip.equals(device.getDeviceIp()));
                            finalDeviceVos.add(deviceVo);
                        }
                    }

                    // 更新设备信息
                    FaceImageBo update = new FaceImageBo();
                    update.setId(faceImageVo.getId());
                    update.setDeviceInfo(JsonUtils.toJsonString(finalDeviceVos));
                    Boolean b = FaceImageServiceImpl.this.updateByBo(update);
                    if (!b) {
                        // 处理更新失败的情况
                        System.err.println("更新设备信息失败，设备IP：" + ip);
                    }
                };

                // 将任务提交到全局线程池执行
                Future<?> future = globalThreadPool.submit(task);
                futures.add(future);
            }

            // 等待所有任务完成
            for (Future<?> future : futures) {
                try {
                    future.get(); // 阻塞，直到任务执行完成
                } catch (ExecutionException | InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        return true;
    }


    public Boolean synchronizeDeviceOne(FaceImageBo faceImageBo) {
        if (ObjectUtils.isNotEmpty(faceImageBo) && ObjectUtils.isEmpty(faceImageBo.getDeviceIp())) {
            throw new ServiceException("请选择要同步的设备");
        }
        if (ObjectUtils.isEmpty(faceImageBo.getStuNum())) {
            throw new ServiceException("请选择要同步的学生信息");
        }
        FaceImageVo faceImageVo = this.selectVoByStuNum(faceImageBo.getStuNum());
        if (ObjectUtils.isEmpty(faceImageVo)) {
            throw new ServiceException("照片入库失败，查询不到此学生");
        }
        String deviceInfo = faceImageVo.getDeviceInfo();
        List<DeviceVo> deviceVos = Utils.parseDeviceVoJson(deviceInfo);
        DeviceVo deviceVo = new DeviceVo();
        File file = new File(faceImageVo.getImageUrl());
        JsonResponse jsonResponse = synchronizeImageService.sendImageIntoDevice(file, faceImageVo.getStuNum(), faceImageBo.getDeviceIp(),faceImageVo.getStudentName());
        if (ObjectUtils.isNotEmpty(jsonResponse)) {
            deviceVo.setDeviceIp(faceImageBo.getDeviceIp());
            deviceVo.setSynchronizeStatus(jsonResponse.getCode().toString());
            deviceVo.setSynchronizeMsg(jsonResponse.getMessage());
        }
        if (CollectionUtils.isNotEmpty(deviceVos)) {
            deviceVos.removeIf(device -> faceImageBo.getDeviceIp().equals(device.getDeviceIp()));
        }
        FaceImageBo update = new FaceImageBo();
        update.setId(faceImageVo.getId());
        JsonUtils.toJsonString(deviceVos);
        update.setDeviceInfo(JsonUtils.toJsonString(deviceVos));
        Boolean b = this.updateByBo(update);
        if (!b) {

        }
        return true;
    }

    public Boolean synchronizeDeviceBatchRemove(FaceImageBo faceImageBo) {
        if (ObjectUtils.isNotEmpty(faceImageBo) && CollectionUtils.isEmpty(faceImageBo.getDeviceIps())) {
            throw new ServiceException("请选择要同步的设备");
        }
        if (ObjectUtils.isNotEmpty(faceImageBo) && CollectionUtils.isEmpty(faceImageBo.getDeviceIps())) {
            throw new ServiceException("请选择要同步的设备");
        }
        List<FaceImageVo> faceImageVos = this.queryList(faceImageBo);
        if (CollectionUtils.isEmpty(faceImageVos)) {
            throw new ServiceException("暂无学生头像可同步");
        }
        for (FaceImageVo faceImageVo : faceImageVos) {
            List<DeviceVo> deviceVos = new ArrayList<>();
            if (StringUtils.isNotEmpty(faceImageVo.getDeviceInfo())) {
                String deviceInfo = faceImageVo.getDeviceInfo();
                deviceVos = Utils.parseDeviceVoJson(deviceInfo);
            }
            for (String ip : faceImageBo.getDeviceIps()) {
                String code="";
                String url = "http://"+ip + "/api/v1/uid/known/" + faceImageBo.getExecutionType();
                DeviceVo deviceVo = new DeviceVo();
                JsonResponse jsonResponse = synchronizeImageService.removeImageFromDevice(faceImageVo.getStuNum(), url);
                if (ObjectUtils.isNotEmpty(jsonResponse)) {
                    deviceVo.setDeviceIp(ip);
                    if(StringUtils.isNotEmpty(jsonResponse.getCode().toString())){
                        if ("delete".equals(faceImageBo.getExecutionType())) {
                            if ("0".equals(jsonResponse.getCode().toString())) {
                                code = "30";
                            } else {
                                code="31";
                            }
                        }
                    }
                    deviceVo.setSynchronizeStatus(code);
                    deviceVo.setSynchronizeMsg(jsonResponse.getMessage());
                }
                if (CollectionUtils.isNotEmpty(deviceVos)) {
                    deviceVos.removeIf(device -> ip.equals(device.getDeviceIp()));
                }
                deviceVos.add(deviceVo);
            }
            FaceImageBo update = new FaceImageBo();
            update.setId(faceImageVo.getId());
            JsonUtils.toJsonString(deviceVos);
            update.setDeviceInfo(JsonUtils.toJsonString(deviceVos));
            Boolean b = this.updateByBo(update);
            if (!b) {

            }
        }
        return true;
    }

    public FaceImageVo selectVoByStuNum(String stuNum) {
        FaceImageVo faceImageVo = baseMapper.selectVoOne(new LambdaQueryWrapper<FaceImage>()
            .eq(StringUtils.isNotEmpty(stuNum), FaceImage::getStuNum, stuNum));
        return faceImageVo;
    }
    public List<FaceImageVo> selectVoListByStuNum(String stuNum) {
        List<FaceImageVo> faceImageVo = baseMapper.selectVoList(new LambdaQueryWrapper<FaceImage>()
            .eq(StringUtils.isNotEmpty(stuNum), FaceImage::getStuNum, stuNum));
        return faceImageVo;
    }

    /**
     * 批量关联学生信息
     */
    @Override
    public Boolean batchCreate(MemberBo bo) {
        List<MemberVo> memberVos = memberService.queryList(bo);
        if (CollectionUtils.isEmpty(memberVos)) {
            throw new ServiceException("系统中无学生信息");
        }

        // 使用线程安全的队列来存储 FaceImage 对象
        Queue<FaceImage> faceImagesQueue = new ConcurrentLinkedQueue<>();
        List<Future<?>> futures = new ArrayList<>();

        // 为每个学生信息创建一个线程任务
        for (MemberVo memberVo : memberVos) {
            Runnable task = () -> {
                FaceImageVo faceImageVo = this.selectVoByStuNum(memberVo.getIdNumber());
                if (ObjectUtil.isNull(faceImageVo)) {
                    FaceImage faceImage = new FaceImage();
                    faceImage.setStuNum(memberVo.getIdNumber());
                    faceImage.setTenantId(memberVo.getTenantId());
                    faceImagesQueue.add(faceImage);
                }
            };
            // 提交任务到线程池
            Future<?> future = globalThreadPool.submit(task);
            futures.add(future);
        }

        // 等待所有任务完成
        for (Future<?> future : futures) {
            try {
                future.get(); // 阻塞，直到任务执行完成
            } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        // 将所有收集到的 FaceImage 对象插入数据库
        if (!faceImagesQueue.isEmpty()) {
            Boolean insertResult = baseMapper.insertBatch(new ArrayList<>(faceImagesQueue));
            if (!insertResult) {
                throw new ServiceException("导入学生失败");
            }
        }

        return true;
    }
}
